package org.cleverframe.modules.erp.service;

import java.io.InputStream;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.cleverframe.common.persistence.Page;
import org.cleverframe.common.service.BaseService;
import org.cleverframe.common.vo.AjaxMessage;
import org.cleverframe.modules.erp.ErpBeanNames;
import org.cleverframe.modules.erp.dao.RawMaterialInfoDao;
import org.cleverframe.modules.erp.entity.RawMaterialInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

/**
 * 原料资料Service<br>
 * 
 * @author LiZW
 * @version 2015年12月23日 下午9:17:41
 */
@Service(ErpBeanNames.RawMaterialInfoService)
public class RawMaterialInfoService extends BaseService
{
    @Autowired
    @Qualifier(ErpBeanNames.RawMaterialInfoDao)
    private RawMaterialInfoDao rawMaterialInfoDao;

    /**
     * 分页查询原料数据<br>
     * 
     * @param page 分页对象
     * @param rawmaterialCode 查询参数：原料编码
     * @param name 查询参数：原料名称
     * @param specification 查询参数：原料规格
     * @param rawmaterialType 查询参数：原料类型
     * @param colorNo 查询参数：原料色号
     * @return
     */
    public Page<RawMaterialInfo> findRawMaterialInfoByPage(
            Page<RawMaterialInfo> page, 
            String rawmaterialCode, 
            String name, 
            String specification, 
            String rawmaterialType, 
            String colorNo)
    {
        return rawMaterialInfoDao.findRawMaterialInfoByPage(page, rawmaterialCode, name, specification, rawmaterialType, colorNo);
    }

    /**
     * 增加原料资料<br>
     * 1.验证“原料名称、原料规格、原料类型、原料色号”组合值不能重复<br>
     * 2.生成原料编码(需要同步)<br>
     * @param rawMaterialInfo 原料实体类
     */
    public synchronized boolean addRawMaterialInfo(RawMaterialInfo rawMaterialInfo, AjaxMessage message)
    {
        /* ----------------------------------原料资料验证---------------------------------- */
        String name = StringUtils.trim(rawMaterialInfo.getName());
        String specification = StringUtils.trim(rawMaterialInfo.getSpecification());
        String rawmaterialType = StringUtils.trim(rawMaterialInfo.getRawmaterialType());
        String colorNo = StringUtils.trim(rawMaterialInfo.getColorNo());
        rawMaterialInfo.setName(name);
        rawMaterialInfo.setSpecification(specification);
        rawMaterialInfo.setRawmaterialType(rawmaterialType);
        rawMaterialInfo.setColorNo(colorNo);
        // 验证原料是否存在
        if (rawMaterialInfoDao.rawMaterialInfoIsRepeat(null, name, specification, rawmaterialType, colorNo))
        {
            message.setMessage("原料信息重复!");
            return false;
        }

        // 计算原料编码
        String rawmaterialMaxCode = rawMaterialInfoDao.getRawMaterialMaxCode();
        StringBuilder str = new StringBuilder();
        for (int i = 0; i < RawMaterialInfo.CODE_NUMBER_LENGTH; i++)
        {
            str.append('0');
        }
        if (StringUtils.isBlank(rawmaterialMaxCode))
        {
            str.append('1');
        }
        else
        {
            rawmaterialMaxCode = rawmaterialMaxCode.replace(RawMaterialInfo.CODE_PREFIX, "").replace(RawMaterialInfo.CODE_SUFFIX, "");
            int max = NumberUtils.toInt(rawmaterialMaxCode, 0) + 1;
            str.append(max);
        }
        rawmaterialMaxCode = str.toString().substring(str.length() - RawMaterialInfo.CODE_NUMBER_LENGTH);
        rawmaterialMaxCode = RawMaterialInfo.CODE_PREFIX + rawmaterialMaxCode + RawMaterialInfo.CODE_SUFFIX;
        rawMaterialInfo.setRawmaterialCode(rawmaterialMaxCode);
        
        /* ----------------------------------原料资料保存---------------------------------- */
        rawMaterialInfoDao.getHibernateDao().save(rawMaterialInfo);
        return true;
    }
    
    /**
     * 更新原料资料<br>
     * 1.判断更新原料资料是否存在<br>
     * 2.不能修改“原料编码”<br>
     * 3.验证“原料名称、原料规格、原料类型、原料色号”组合值不能重复<br>
     * @param rawMaterialInfo 原料实体类
     */
    public boolean updateRawMaterialInfo(RawMaterialInfo rawMaterialInfo, AjaxMessage message)
    {
        /* ----------------------------------原料资料更新验证---------------------------------- */
        RawMaterialInfo oldRawMaterialInfo = rawMaterialInfoDao.getHibernateDao().get(rawMaterialInfo.getId());
        if (oldRawMaterialInfo == null)
        {
            message.setMessage("更新的原料不存在");
            return false;
        }
        if (oldRawMaterialInfo.getRawmaterialCode().equals(rawMaterialInfo.getRawmaterialCode()) == false)
        {
            message.setMessage("不能修改原料编码");
            return false;
        }
        
        String name = StringUtils.trim(rawMaterialInfo.getName());
        String specification = StringUtils.trim(rawMaterialInfo.getSpecification());
        String rawmaterialType = StringUtils.trim(rawMaterialInfo.getRawmaterialType());
        String colorNo = StringUtils.trim(rawMaterialInfo.getColorNo());
        rawMaterialInfo.setName(name);
        rawMaterialInfo.setSpecification(specification);
        rawMaterialInfo.setRawmaterialType(rawmaterialType);
        rawMaterialInfo.setColorNo(colorNo);
        if (rawMaterialInfoDao.rawMaterialInfoIsRepeat(rawMaterialInfo.getId(), name, specification, rawmaterialType, colorNo))
        {
            message.setMessage("原料信息重复!");
            return false;
        }
        
        /* ----------------------------------原料资料更新---------------------------------- */
        rawMaterialInfoDao.getHibernateDao().getSession().evict(oldRawMaterialInfo);
        rawMaterialInfoDao.getHibernateDao().update(rawMaterialInfo);
        return true;
    }
    
    /**
     * 删除原料资料<br>
     * 1.判断删除原料资料是否存在<br>
     * 2.原料如果被其他地方引用(比如：库存)，则不能删除<br>
     * @param rawMaterialInfo 原料实体类
     */
    public boolean deleteRawMaterialInfo(RawMaterialInfo rawMaterialInfo, AjaxMessage message)
    {
        /* ----------------------------------原料资料删除验证---------------------------------- */
        RawMaterialInfo oldRawMaterialInfo = rawMaterialInfoDao.getHibernateDao().get(rawMaterialInfo.getId());
        if (oldRawMaterialInfo == null)
        {
            message.setMessage("删除的原料不存在");
            return false;
        }
        
        // TODO 原料如果被其他地方引用(比如：库存)，则不能删除
        
        /* ----------------------------------原料资料删除---------------------------------- */
        rawMaterialInfoDao.getHibernateDao().delete(oldRawMaterialInfo);
        return true;
    }
    
    
    /**
     * 根据多个id查询数据
     * @param ids 查询参数：多个ID，如 12,19,15,255
     * @return 
     */
    public List<RawMaterialInfo> findRawMaterialInfoByIds(String ids)
    {
        return rawMaterialInfoDao.findRawMaterialInfoByIds(ids);
    }
    
    /**
     * 数据导出创建Excel
     * */
    public HSSFWorkbook exportRawMaterialInfo(List<RawMaterialInfo> rawMaterialInfoList)
    {
        HSSFWorkbook workbook = new HSSFWorkbook();
        HSSFSheet sheet = workbook.createSheet("原料资料");
        sheet.setColumnWidth(0, 18 * 256);
        sheet.setColumnWidth(1, 30 * 256);
        sheet.setColumnWidth(2, 20 * 256);
        sheet.setColumnWidth(3, 20 * 256);
        sheet.setColumnWidth(4, 20 * 256);
        sheet.setColumnWidth(5, 30 * 256);
        HSSFRow row = sheet.createRow(0);
        row.createCell(0).setCellValue("编码");
        row.createCell(1).setCellValue("名称");
        row.createCell(2).setCellValue("规格");
        row.createCell(3).setCellValue("类型");
        row.createCell(4).setCellValue("色号");
        row.createCell(5).setCellValue("备注信息");
        int rowCount = 0;
        for (RawMaterialInfo rawMaterialInfo : rawMaterialInfoList)
        {
            rowCount++;
            row = sheet.createRow(rowCount);
            row.createCell(0).setCellValue(rawMaterialInfo.getRawmaterialCode());
            row.createCell(1).setCellValue(rawMaterialInfo.getName());
            row.createCell(2).setCellValue(rawMaterialInfo.getSpecification());
            row.createCell(3).setCellValue(rawMaterialInfo.getRawmaterialType());
            row.createCell(4).setCellValue(rawMaterialInfo.getColorNo());
            row.createCell(5).setCellValue(rawMaterialInfo.getRemarks());
        }
        return workbook;
    }
    
    /**
     * 导入数据<br>
     * @param inputStream 导入数据文件输入流
     * @return
     * @throws Exception 导入数据失败抛出异常
     */
    public HSSFWorkbook importRawMaterialInfo(InputStream inputStream) throws Exception
    {
        HSSFWorkbook workbook = new HSSFWorkbook(inputStream);
        HSSFSheet sheet = workbook.getSheet("原料资料");
        sheet.setColumnWidth(5, 20 * 256);
        sheet.setColumnWidth(6, 30 * 256);
        int rowCount = -1;
        for (Row row : sheet)
        {
            rowCount++;
            if (rowCount == 0)
            {
                row.createCell(5).setCellValue("是否导入成功");
                row.createCell(6).setCellValue("导入失败原因");
                continue;
            }
            RawMaterialInfo rawMaterialInfo = new RawMaterialInfo();
            AjaxMessage message = new AjaxMessage();
            try
            {
                rawMaterialInfo.setName(row.getCell(0).getStringCellValue());
                rawMaterialInfo.setSpecification(row.getCell(1).getStringCellValue());
                rawMaterialInfo.setRawmaterialType(row.getCell(2).getStringCellValue());
                rawMaterialInfo.setColorNo(row.getCell(3).getStringCellValue());
                rawMaterialInfo.setRemarks(row.getCell(4).getStringCellValue());
                if(StringUtils.isBlank(rawMaterialInfo.getName()))
                {
                    throw new Exception("名称不能为空");
                }
                if(StringUtils.isBlank(rawMaterialInfo.getSpecification()))
                {
                    throw new Exception("规格不能为空");
                }
                boolean flag = addRawMaterialInfo(rawMaterialInfo, message);
                message.setSuccess(flag);
            }
            catch (Exception e)
            {
                message.setMessage(e.getMessage());
                message.setSuccess(false);
            }
            if (message.isSuccess())
            {
                row.createCell(5).setCellValue("成功");
            }
            else
            {
                row.createCell(5).setCellValue("失败");
                row.createCell(6).setCellValue(message.getMessage());
            }
        }
        return workbook;
    }
    
    
    /**
     * 模糊查询原料信息，使用分页<br>
     * @return 分页数据
     */
    public Page<RawMaterialInfo> findRawMaterialInfoByParam(Page<RawMaterialInfo> page, String q)
    {
        return rawMaterialInfoDao.findRawMaterialInfoByParam(page, q);
    }
    
    /**
     * 分页查询供应商供应的原料信息<br>
     * @param page 分页数据
     * @param supplierId 查询参数：供应商ID
     * @return 分页数据
     */
    public Page<RawMaterialInfo> findSupplierRawmaterial(Page<RawMaterialInfo> page, Long supplierId)
    {
        return rawMaterialInfoDao.findSupplierRawmaterial(page, supplierId);
    }
    
    /**
     * 查询原料库存<br>
     * @param rawmaterialCode 查询参数：原料编码
     * @param name 参询参数：原料名称
     * @param specification 查询参数：规格
     * @return
     */
    public Page<Map<Object, Object>> findRawmaterialInventory(Page<Map<Object, Object>> page, String rawmaterialCode, String name, String specification)
    {
        return rawMaterialInfoDao.findRawmaterialInventory(page, rawmaterialCode, name, specification);
    }
}
